using System;
using System.Collections;
using System.Data.Linq.Mapping;
using System.Runtime.Serialization;
using Portal.Data.Helper;
using System.Linq;
using Portal.Core.Binding.FormBuilder;

namespace Portal.Data.Entity
{
    [Table(Name = "dbo.Permission"), Serializable, DataContractAttribute]
    public class Permission : BaseObject
    {
        #region constant
        //Module canbe
        public const int NONE = 0;
        public const int MODULE_VIEW = 0x1;
        public const int MODULE_EDIT = 0x2;
        public const int MODULE_DELETE = 0x4;
        public const int MODULE_LISTVIEW = 0x8;


        ////workflow canbe
        //public const int WF_DRAFT = 0x10000;
        public const int WF_SUBMIT = 0x20000;
        public const int WF_APPROVE = 0x40000;
        public const int WF_PUBLISH = 0x80000;

        //security
        public const int CONTROL = 0x10000000;
        public const int VIEW_ADMIN_TOOL = 0x20000000;

        //all
        public const int ALL = 0x7FFFFFFF;

        #endregion

        #region Properties
        public int ID { get { return Permission_ID; } set { Permission_ID = value; } }

        [SkipBinding]
        [ColumnAttribute(Name = "Permission_ID", IsPrimaryKey = true, IsDbGenerated = true)]
        [DataMemberAttribute(Order = 1)]
        public int Permission_ID { get; set; }

        [ColumnAttribute(Name = "User_ID")]
        [DataMemberAttribute(Order = 2)]
        public int? User_ID { get; set; }

        [ColumnAttribute(Name = "Object_ID")]
        [DataMemberAttribute(Order = 3)]
        public Int64 Object_ID { get; set; }

        [ColumnAttribute(Name = "Permissions")]
        [DataMemberAttribute(Order = 4)]
        public int Permissions { get; set; }


        #endregion


        #region Methods
        public static Permission FindByPrimaryKey(object objectid)
        {
            return FindByPrimaryKey<Permission>(objectid);
        }

        /// <summary>
        /// Get permission object by User and one Permission matched
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public static Permission Load(int userId, int p)
        {
            const string sql = "select * from Permission where User_ID = {0} and Permissions & {1} ={1}";
            var result = LINQHelper.GetFirst<Permission>(sql, userId, p);
            return result;
        }
        public static Permission Load(int userId, Int64 portalId)
        {
            const string sql = "select * from Permission where User_ID = {0} and Object_ID = {1}";
            var result = LINQHelper.GetFirst<Permission>(sql, userId, portalId);
            return result;
        }

        public static int Load(int userId, IList portals)
        {
            var p = NONE;
            var pIds = GetListId(portals);

            const string sql = "select * from Permission where User_ID = {0} and Object_ID in ({1})";
            var result = LINQHelper.GetList<Permission>(sql, userId, pIds);

            for (int i = 0; i < result.Count; i++)
            {
                var per = (Permission)result[i];
                p = p | per.Permissions;
            }
            return p;
        }
        public static bool CheckHasPermission(int userId, Int64 portalId, int p)
        {
            const string sql = "select count(*) from Permission where User_ID= {0} and Object_ID = {1} and Permissions & {2} >0";
            var result = LINQHelper.GetFirst<int>(sql, userId, portalId, p);
            return result > 0;
        }

        public static bool CheckAtLeastOnePermission(IList listPortal, int p)
        {
            var pIds = GetListId(listPortal);
            const string sql = "select count(*) from Permission where User_ID = {0} and Permissions & {1} >0 and Object_ID in ({2})";
            var result = LINQHelper.GetFirst<int>(sql, PortalContext.CurrentUser.ID, p, pIds);
            return result > 0;
        }

        public static int RemoveByUser(int userId)
        {
            const string sql = "delete Permission where User_ID={0}";
            return LINQHelper.ExecuteNonQuery(sql, userId);
        }

        public static int RemoveByObject(Int64 portalId)
        {
            const string sql = "delete Permission where Object_ID={0}";
            return LINQHelper.ExecuteNonQuery(sql, portalId);
        }

        #endregion Methods


        #region LOGIC
        public static string GetListId(IList list)
        {
            var result = "";
            foreach (Permission item in list)
            {
                result += item.ID + ",";
            }
            if (result.Length > 0)
                result = result.Substring(0, result.Length - 1);   //remove last comma
            return result;
        }

        /// <summary>
        /// MODULE_VIEW | MODULE_EDIT | MODULE_DELETE
        /// </summary>
        /// <returns></returns>
        public static int CanViewModule()
        {
            return MODULE_VIEW | MODULE_EDIT | MODULE_DELETE;
        }

        /// <summary>
        /// MODULE_EDIT | MODULE_DELETE
        /// </summary>
        /// <returns></returns>
        public static int CanEditModule()
        {
            return MODULE_EDIT | MODULE_DELETE;
        }
        /// <summary>
        /// MODULE_DELETE
        /// </summary>
        /// <returns></returns>
        public static int CanDeleteModule()
        {
            return MODULE_DELETE;
        }

        /// <summary>
        /// WF_SUBMIT | WF_APPROVE | WF_PUBLISH
        /// </summary>
        /// <returns></returns>
        public static int CanSubmitContent()
        {
            return WF_SUBMIT | WF_APPROVE | WF_PUBLISH;
        }
        /// <summary>
        /// WF_APPROVE | WF_PUBLISH
        /// </summary>
        /// <returns></returns>
        public static int CanApproveContent()
        {
            return WF_APPROVE | WF_PUBLISH;
        }
        /// <summary>
        /// WF_SUBMIT | WF_APPROVE | WF_PUBLISH
        /// </summary>
        /// <returns></returns>
        public static int CanDeleteContent()
        {
            return WF_APPROVE | WF_PUBLISH;
        }

        /// <summary>
        /// WF_PUBLISH
        /// </summary>
        /// <returns></returns>
        public static int CanPublishContent()
        {
            return WF_PUBLISH;
        }
        /// <summary>
        /// WF_PUBLISH
        /// </summary>
        /// <returns></returns>
        public static int CanUnPublishContent()
        {
            return WF_PUBLISH;
        }
        /// <summary>
        /// WF_APPROVE | WF_PUBLISH
        /// </summary>
        /// <returns></returns>
        public static int CanRejectToApprovedContent()
        {
            return WF_APPROVE | WF_PUBLISH;
        }
        /// <summary>
        /// WF_APPROVE | WF_PUBLISH
        /// </summary>
        /// <returns></returns>
        public static int CanRejectToSubmitedContent()
        {
            return WF_APPROVE | WF_PUBLISH;
        }
        /// <summary>
        /// WF_DRAFT | WF_SUBMIT | WF_APPROVE | WF_PUBLISH
        /// </summary>
        /// <returns></returns>
        public static int CanViewCategories()
        {
            return WF_SUBMIT | WF_APPROVE | WF_PUBLISH;
        }

        #region MODULE block START
        /*------------------------MODULE block START-------------*/
        public bool ModuleCanView
        {
            get
            {
                return HasPermission(MODULE_VIEW);
            }
            set
            {
                if (value)
                {
                    AddPermission(MODULE_VIEW);
                }
                else
                {
                    RemovePermission(MODULE_VIEW);
                }
            }
        }

        public bool ModuleCanDelete
        {
            get
            {
                return HasPermission(MODULE_DELETE);
            }
            set
            {
                if (value)
                {
                    AddPermission(MODULE_DELETE);
                }
                else
                {
                    RemovePermission(MODULE_DELETE);
                }
            }
        }

        public bool ModuleCanEdit
        {
            get
            {
                return HasPermission(MODULE_EDIT);
            }
            set
            {
                if (value)
                {
                    AddPermission(MODULE_EDIT);
                }
                else
                {
                    RemovePermission(MODULE_EDIT);
                }
            }
        }

        public bool ModuleCanControl
        {
            get
            {
                return HasPermission(CONTROL);
            }
            set
            {
                if (value)
                {
                    AddPermission(CONTROL);
                }
                else
                {
                    RemovePermission(CONTROL);
                }
            }
        }

        public bool ModuleCanViewAdminTool
        {
            get
            {
                return HasPermission(VIEW_ADMIN_TOOL);
            }
            set
            {
                if (value)
                {
                    AddPermission(VIEW_ADMIN_TOOL);
                }
                else
                {
                    RemovePermission(VIEW_ADMIN_TOOL);
                }
            }
        }

        /*------------------------MODULE block END-------------*/
        #endregion

        #region WorkFlow block START

        public bool WorkFlowCanSubmit
        {
            get
            {
                return HasPermission(WF_SUBMIT);
            }
            set
            {
                if (value)
                {
                    AddPermission(WF_SUBMIT);
                }
                else
                {
                    RemovePermission(WF_SUBMIT);
                }
            }
        }

        public bool WorkFlowCanApprove
        {
            get
            {
                return HasPermission(WF_APPROVE);
            }
            set
            {
                if (value)
                {
                    AddPermission(WF_APPROVE);
                }
                else
                {
                    RemovePermission(WF_APPROVE);
                }
            }
        }

        public bool WorkFlowCanPublish
        {
            get
            {
                return HasPermission(WF_PUBLISH);
            }
            set
            {
                if (value)
                {
                    AddPermission(WF_PUBLISH);
                }
                else
                {
                    RemovePermission(WF_PUBLISH);
                }
            }
        }

        /*------------------------WorkFlow block END-------------*/
        #endregion
        #endregion

        #region implement

        public Permission()
        {
            Permissions = NONE;
        }

        public Permission(int permission)
        {
            Permissions = permission;
        }

        public bool HasPermission(int canbe)
        {
            return HasPermission(Permissions, canbe);
        }

        public static bool HasPermission(int permission, int canbe)
        {
            //            return (permission & canbe) == canbe;
            return (permission & canbe) > 0;
        }

        public void RemovePermission(int canbe)
        {
            if (HasPermission(canbe))
            {
                Permissions = Permissions - canbe;
            }
        }
        public static int RemoveModulePermission(int fromPermission)
        {
            return fromPermission - CanViewModule();
        }
        public static int RemoveContentPermission(int fromPermission)
        {
            return fromPermission - CanSubmitContent();
        }
        public void AddPermission(int canbe)
        {
            Permissions = Permissions | canbe;
        }

        #endregion
    }
}
